package org.penguin.study.bk.service.impl

import org.penguin.study.bk.entity.Address
import org.penguin.study.bk.entity.Good
import org.penguin.study.bk.entity.Order
import org.penguin.study.bk.service.CompletableFutureService
import org.springframework.stereotype.Service
import java.util.*
import java.util.concurrent.CompletableFuture
import java.util.stream.Collectors
import java.util.stream.Stream

@Service
class CompletableFutureServiceImpl : CompletableFutureService {

    @Override
    override fun createOrder(order: Order): String {
        val goodIdList: MutableList<String> = ArrayList()
        val goodIdSet: Set<String> = order.products.keys
        goodIdList.addAll(goodIdSet)

        val userId = "1234567890"
        val addressCompletableFuture = getAddress(userId)
        val goodListCompletableFuture = getGoodList(goodIdList)
        CompletableFuture.allOf(goodListCompletableFuture, addressCompletableFuture).thenApply {
            Stream.of(
                goodListCompletableFuture,
                addressCompletableFuture
            ).map { it.join() }
                .collect(Collectors.toList())
        }.thenApply {
            doOrder(it[0] as List<Good>, it[1] as Address)
        }.join()
        return "下单处理中"
    }

    private fun getGoodList(goodIdList: List<String>): CompletableFuture<List<Good>> {
        return CompletableFuture.supplyAsync {
            println("Terry ->检查商品库存中")
            Thread.sleep(3000L)
            goodIdList.stream()
                .map { item: String? -> Good(item) }
                .collect(Collectors.toList())
        }
    }

    private fun getAddress(userId: String): CompletableFuture<Address> {
        return CompletableFuture.supplyAsync {
            println("Terry ->处理地址中")
            Thread.sleep(8000L)
            Address(userId + Random().nextInt() + "address")
        }
    }

    private fun doOrder(goods: List<Good>, address: Address): CompletableFuture<String> {
        println("Terry ->已取得商品和地址信息，满足库存即可成功: <goods:>$goods,<address:>$address")
        return CompletableFuture.supplyAsync { "ok" }
    }
}
